package com.example.administrator.seppdzxing.decode;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import com.example.administrator.seppdzxing.ICaptureView;
import com.example.administrator.seppdzxing.R;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.common.GlobalHistogramBinarizer;
import com.google.zxing.common.HybridBinarizer;
import java.io.ByteArrayOutputStream;
import java.util.Map;

public class DecodeHandler extends Handler {

	private final ICaptureView captureView;
	private final MultiFormatReader multiFormatReader;
	private boolean running = true;
	private Map<DecodeHintType, Object> hints;

	public DecodeHandler(ICaptureView captureView, Map<DecodeHintType, Object> hints) {
		this.hints = hints;
		multiFormatReader = new MultiFormatReader();
		multiFormatReader.setHints(hints);
		this.captureView = captureView;
	}

	@Override
	public void handleMessage(Message message) {
		if (!running) {
			return;
		}
		if (message.what == R.id.decode) {
			if(message.obj == null&&message.arg1==0&&message.arg2==0){
				Message message1 = Message.obtain(captureView.getScanHandler(), R.id.decode_failed);
				message1.sendToTarget();
			}else {
				decode((byte[]) message.obj, message.arg1, message.arg2);
			}
		} else if (message.what == R.id.quit) {
			running = false;
			Looper.myLooper().quit();
		}  else if(message.what == R.id.decode_bitmap){
			Result rawResult = decodeBitmap( message.obj);
			sendMessage(rawResult);
		}
	}

	private void sendMessage(Result rawResult) {
		Handler handler = captureView.getScanHandler();
		if(rawResult!=null){
			if (handler != null) {
				Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult);
				Bundle bundle = new Bundle();
				message.setData(bundle);
				message.sendToTarget();
			}
		}else {
			if (handler != null) {
				Message message = Message.obtain(handler, R.id.decode_bitmap_failed);
				message.sendToTarget();
			}
		}
	}


	/**
	 * Decode the data within the viewfinder rectangle, and time how long it
	 * took. For efficiency, reuse the same reader objects from one decode to
	 * the next.
	 * 
	 * @param data
	 *            The YUV preview frame.
	 * @param width
	 *            The width of the preview frame.
	 * @param height
	 *            The height of the preview frame.
	 */
	private void decode(byte[] data, int width, int height) {
		long startTime = System.currentTimeMillis();
		Handler handler = captureView.getScanHandler();
		try {
			Size size = captureView.getCameraManager().getPreviewSize();
			// 这里需要将获取的data翻转一下，因为相机默认拿的的横屏的数据
//			byte[] rotatedData = new byte[data.length];
//			long befor = System.currentTimeMillis();
//			for (int y = 0; y < size.height; y++) {
//				for (int x = 0; x < size.width; x++)
//					rotatedData[x * size.height + size.height - y - 1] = data[x + y * size.width];
//			}
//			long l = System.currentTimeMillis() - befor;
//			// 宽高也要调整
//			int tmp = size.width;
//			size.width = size.height;
//			size.height = tmp;

			Result rawResult = null;
			PlanarYUVLuminanceSource source = buildLuminanceSource(data, size.width, size.height);
//			if(source!=null){
//                Bundle bundle = new Bundle();
//                bundleThumbnail(source, bundle);
//                Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult);
//                message.setData(bundle);
//				message.sendToTarget();
//            }

			if (source != null) {
				BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
				try {
					rawResult = multiFormatReader.decodeWithState(bitmap);
					long l = System.currentTimeMillis() - startTime;
					Log.d("AAA","解析一次的间隔为："+l);
				} catch (ReaderException re) {
					// continue
				} finally {
					multiFormatReader.reset();
				}
			}

			if (rawResult != null) {
				// Don't log the barcode contents for security.
				if (handler != null) {
					Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult);
					Bundle bundle = new Bundle();
				bundleThumbnail(source, bundle);
					message.setData(bundle);
					message.sendToTarget();
				}
			} else {
				if (handler != null) {
					Message message = Message.obtain(handler, R.id.decode_failed);
					message.sendToTarget();
				}
			}

		}catch (Exception e){
			if (handler != null) {
				Message message = Message.obtain(handler, R.id.decode_failed);
				message.sendToTarget();
			}
		}

	}

	private Result decodeBitmap(Object picturePath) {
		Result result = null;
		try {
			BitmapFactory.Options options = new BitmapFactory.Options();
			options.inJustDecodeBounds = true;
			BitmapFactory.decodeFile((String) picturePath, options);
			int sampleSize = options.outHeight / 400;
			if (sampleSize <= 0) {
				sampleSize = 1;
			}
			options.inSampleSize = sampleSize;
			options.inJustDecodeBounds = false;
			Bitmap bitmap = BitmapFactory.decodeFile((String) picturePath, options);
			RGBLuminanceSource source;
				int width = bitmap.getWidth();
				int height = bitmap.getHeight();
				int[] pixels = new int[width * height];
				bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
				source = new RGBLuminanceSource(width, height, pixels);
				result = new MultiFormatReader().decode(new BinaryBitmap(new HybridBinarizer(source)), hints);
				if(result == null){
					result = new MultiFormatReader().decode(new BinaryBitmap(new GlobalHistogramBinarizer(source)), hints);
				}

			} catch (Exception e) {
			e.printStackTrace();
			}
		return result;
	}

	/**
	 * 生成图片
	 * @param source
	 * @param bundle
	 */
	private static void bundleThumbnail(PlanarYUVLuminanceSource source, Bundle bundle) {
		int[] pixels = source.renderThumbnail();
		int width = source.getThumbnailWidth();
		int height = source.getThumbnailHeight();
		Bitmap bitmap = Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.ARGB_8888);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		bitmap.compress(Bitmap.CompressFormat.JPEG, 50, out);
		bundle.putByteArray(DecodeThread.BARCODE_BITMAP, out.toByteArray());
	}

	/**
	 * A factory method to build the appropriate LuminanceSource object based on
	 * the format of the preview buffers, as described by Camera.Parameters.
	 * 
	 * @param data
	 *            A preview frame.
	 * @param width
	 *            The width of the image.
	 * @param height
	 *            The height of the image.
	 * @return A PlanarYUVLuminanceSource instance.
	 */
	public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
		Rect rect = captureView.getCropRect();
//		Log.d("AAA","rect.left "+rect.left+" rect.top "+rect.top+" rect.right "+rect.right+" rect.bootom "+rect.bottom);
		if (rect == null) {
			return null;
		}
		return new PlanarYUVLuminanceSource(data, width, height, rect.top, rect.left, rect.height(), rect.width(), false);
	}

}
